home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / info-service / www / src / midaswww-1.0 / midasingot.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-11-16  |  14.2 KB  |  532 lines

  1. #include <Mrm/MrmAppl.h>                        /* Motif Toolkit and MRM */
  2. #include "midaslist.h"     
  3. #include "midasoperand.h"
  4. #include "midaswidget.h"
  5. #include "midasshell.h"
  6. #include <string.h>
  7.  
  8. MidasOperand MidasConvertFromInteger();
  9. MidasOperand MidasConvertFromString();
  10. MidasOperand MidasConvertFromBoolean();
  11. MidasWidget *MidasWidgetToMW();
  12. MidasShell  *MidasGetShell();
  13. char *MidasGetWidgetName();
  14. char *MidasConvertToString();
  15.  
  16. static char *Option = "ExecuteWhenCreated";
  17.  
  18. typedef struct _IR {char *Command; Boolean ExecuteWhenCreated; } IngotParm;
  19.  
  20. #define Offset(field) XtOffsetOf(IngotParm,field)
  21.  
  22. static XtResource resources[] = {
  23.       {"midasIngots","MidasIngots",XtRString ,sizeof(char *) ,Offset(Command)           ,XtRImmediate,(XtPointer)0},
  24.       {"midasIngots","MidasIngots",XtRBoolean,sizeof(Boolean),Offset(ExecuteWhenCreated),XtRImmediate,(XtPointer)True}};
  25.  
  26. #undef Offset
  27.  
  28. static List *IngotRList;
  29.  
  30. struct Ingot {
  31.    Boolean              Valued;
  32.    MidasOperand         Operand;
  33.    char                *Command;
  34.    Widget               Parent;
  35.    struct Ingot        *ValueOwner;
  36.    List                *CallbackList;
  37.    Boolean              ExecuteWhenCreated;
  38. };          
  39. typedef struct Ingot Ingot;
  40.  
  41.  
  42. static XtConvertArgRec ConvertWidgetArg[] = {{XtBaseOffset,0,sizeof(Widget)}};
  43.  
  44. Ingot *MidasFindIngotHere(w,Name)
  45. Widget w;
  46. char *Name;
  47. {
  48.     MidasWidget *mw = MidasWidgetToMW(w);
  49.     ListItem *i;
  50.     List *TList = mw->IngotList; 
  51.  
  52.     if (TList != NULL)
  53.       {
  54.         i = MidasFindItemInList(TList,Name);
  55.         if (i != 0) return i->Pointer;
  56.       }
  57.     return 0;
  58.  
  59. }
  60. Ingot *MidasFindIngot(w,Name)
  61. Widget w;
  62. char *Name;
  63. {
  64.     MidasShell *ms = MidasGetShell(w);
  65.  
  66.     for (;; w = XtParent(w))
  67.       {
  68.         Ingot *T = MidasFindIngotHere(w,Name);
  69.         if (T != 0) return T;
  70.         if (w == ms->Widget) break; 
  71.       }      
  72.     return 0;
  73. }
  74. static void MidasDestroyIngot(T)
  75. Ingot *T;
  76. /*
  77.     This routine is called from MidasDestroyIngots during the destruction of
  78.     a widget that has ingots. It assumes that all child widgets are also being 
  79.     destroyed and therefore does not worry about them.
  80. */
  81. {
  82.     if (!T->Valued) 
  83.       {
  84.         Ingot *ValueOwner = T->ValueOwner;
  85.         List *CallbackList = ValueOwner->CallbackList;
  86.         if (CallbackList != 0) 
  87.           {
  88.             ListItem *item;
  89.             for (item = CallbackList->First; item != 0 ; item = item->Next)
  90.               {
  91.                 if (item->Pointer == T) 
  92.                   {
  93.                    item->Pointer = 0; 
  94.                    MidasRemoveItemFromList(CallbackList,item);
  95.                    break;
  96.                   }
  97.               }
  98.           } 
  99.       }
  100.     else if (T->Operand.Dynamic) XtFree((char *)T->Operand.Value.P);
  101.     if (T->CallbackList != 0) MidasDestroyList(T->CallbackList);
  102.     XtFree(T->Command);
  103. }
  104. void MidasDestroyIngots(mw)
  105. MidasWidget *mw;
  106. /*
  107.  *  This routine is called whenever a widget that has ingots
  108.  *  goes and gets itself destroyed.
  109.  */
  110. {
  111.     ListItem *item;
  112.     List *TList = mw->IngotList;
  113.  
  114.     for (item = TList->First; item != 0; item = item->Next)
  115.       {
  116.         Ingot *T = item->Pointer;
  117.         MidasDestroyIngot(T);
  118.         item->Pointer = 0;
  119.       } 
  120.     MidasDestroyList(TList);
  121. }
  122. Ingot *MidasCreateIngot(w,Name)
  123. Widget w;
  124. char *Name;
  125. /*
  126.     If this ingot does not already have an explicit ingot of this name it is created.
  127.     A pointer to the (newly created) ingot is returned;
  128.     A created ingot initially has no value and no callbacks;
  129. */
  130. {
  131.     MidasWidget *mw = MidasWidgetToMW(w);
  132.     Ingot *T;
  133.     ListItem *item;
  134.     List *TList = mw->IngotList;
  135.  
  136.     if (TList == NULL) 
  137.       {
  138.         mw->IngotList = TList = MidasCreateEmptyList(XtName(w));
  139.       }
  140.  
  141.     item = MidasFindItemInList(TList,Name);
  142.     if (item == 0)
  143.       {
  144.         T = XtNew(Ingot);
  145.         T->CallbackList = 0;
  146.         T->Command = 0;
  147.         T->Parent = w;
  148.         T->ValueOwner = 0;
  149.         T->Valued = FALSE;
  150.         T->ExecuteWhenCreated = TRUE;
  151.  
  152.         item = MidasAddItemToList(TList,Name);
  153.         item->Pointer = T;
  154.       }
  155.     else T = item->Pointer;
  156.     return T;
  157. }
  158. void MidasInheritIngotValue(T,Name)
  159. Ingot *T;
  160. char *Name;
  161. {
  162.     Ingot *ValueOwner;
  163.     MidasShell *ms = MidasGetShell(T->Parent);
  164.     if (strncmp(Name,"Midas",5) && ms->Widget != T->Parent) 
  165.       ValueOwner = MidasFindIngot(XtParent(T->Parent),Name);
  166.     else ValueOwner = 0;
  167.  
  168.     if (ValueOwner == 0)
  169.       {
  170.         T->Valued = TRUE;
  171.         T->Operand.Value.P   = (XtPointer)"";
  172.         T->Operand.Dynamic = FALSE;
  173.         T->Operand.Type    = MString;
  174.       }
  175.     else 
  176.       {
  177.         if (ValueOwner->Valued == 0) ValueOwner = ValueOwner->ValueOwner;
  178.         T->ValueOwner = ValueOwner; 
  179.       }
  180.  
  181. #ifdef debug
  182.     if (T->Valued) printf("Ingot %s in %s did not ingerit a value\n",Name,XtName(T->Parent));
  183.     else           printf("Ingot %s inherited value %s from %s\n",Name,ValueOwner->Operand.Value,
  184.                                                                   XtName(ValueOwner->Parent));
  185. #endif
  186. }
  187. void MidasSetIngotValue(T,Operand)
  188. Ingot *T;
  189. MidasOperand Operand;
  190. /*
  191.     This routine sets the value of the specified ingot
  192.     and calls the value changed callbacks belonging to the ingot
  193. */
  194.     if (T->Valued && T->Operand.Dynamic) XtFree((char *)T->Operand.Value.P);
  195.     T->Operand = Operand;
  196. /*
  197.  *  BIG KLUGE .. must be fixed soon
  198.  */
  199.     if (strcmp(Operand.Type,MString)==0 && Operand.Dynamic==FALSE)
  200.       {
  201.         T->Operand.Value.P = XtNewString(Operand.Value.P);
  202.         T->Operand.Dynamic = TRUE;
  203.       }
  204.     T->Valued = TRUE;
  205.  
  206.     if (T->Command != 0) MidasDispatchCommandCallback(T->Parent,T->Command,0);
  207.   
  208.     if (T->CallbackList != 0)
  209.       {
  210.         ListItem *item;
  211.         for (item = T->CallbackList->First; item != 0; item = item->Next)
  212.           {
  213.             Ingot *T = item->Pointer;
  214.             MidasDispatchCommandCallback(T->Parent,T->Command,0);
  215.           }
  216.       }
  217. }
  218. void MidasSetCallbackValue(T,Command)
  219. Ingot *T;
  220. char *Command;
  221. {
  222.     Widget SW, w = T->Parent;
  223.     MidasShell *ms = MidasGetShell(w);
  224.  
  225.     if (T->Command == 0)
  226.       {
  227.         if (T->Valued == 0)
  228.           {
  229.             ListItem *item;
  230.             Ingot *ValueOwner = T->ValueOwner;
  231.             if (ValueOwner->CallbackList == 0) ValueOwner->CallbackList = MidasCreateEmptyList("");
  232.             item = MidasAddItemToListPos(ValueOwner->CallbackList,XtName(w),0);
  233.             item->Pointer = T;
  234.           } 
  235.       }   
  236.     else XtFree(T->Command);
  237.     T->Command = XtNewString(Command);
  238. }
  239. MidasOperand MidasGetIngotValue(T)
  240. Ingot *T;
  241. {
  242.    MidasOperand Temp;
  243.    if (T->Valued == 0) T = T->ValueOwner;
  244.    Temp = T->Operand;
  245.    Temp.Dynamic = FALSE; /* The ingot retains ownership of the operand */
  246.    return Temp;
  247. }
  248. char *MidasGetCallbackValue(T)
  249. Ingot *T;
  250. {
  251.    if (T->Command == 0) return XtNewString("");
  252.    else                 return XtNewString(T->Command);
  253. }
  254. MidasOperand MidasGetCallback(w,Name)
  255. Widget w;
  256. char *Name;
  257. {
  258.    MidasOperand Temp;
  259.    Ingot *T = MidasFindIngotHere(w,Name);
  260.    if (T == 0) 
  261.      {
  262.        Temp.Value.P = "";
  263.        Temp.Dynamic = FALSE;
  264.      }
  265.    else 
  266.      {
  267.        Temp.Value.P = MidasGetCallbackValue(T);
  268.        Temp.Dynamic = TRUE;
  269.      }
  270.    Temp.Type = MString;
  271.    return Temp;
  272. }
  273. MidasOperand MidasGetCreateCallback(w)
  274. Widget w;
  275. {
  276.    Ingot *T = MidasFindIngotHere(w,"midasCreateCallback");
  277.    if (T == 0) 
  278.      {
  279.        MidasOperand Temp;
  280.        Temp.Value.P = "";
  281.        Temp.Dynamic = FALSE;
  282.        Temp.Type = MString;
  283.        return Temp;
  284.      } 
  285.    else return MidasGetIngotValue(T);   
  286. }
  287. MidasOperand MidasGetIngot(w,Name)
  288. Widget w;
  289. char *Name;
  290. {
  291.    Ingot *T = MidasFindIngot(w,Name);
  292.    if (T == 0) MidasError("Can not find ingot %s",Name);
  293.    return MidasGetIngotValue(T);   
  294. }
  295. MidasOperand MidasGetValueOwner(w,Name)
  296. Widget w;
  297. char *Name;
  298. {
  299.    MidasOperand Temp;
  300.    Ingot *T = MidasFindIngot(w,Name);
  301.    if (T == 0) MidasError("Can not find ingot %s",Name);
  302.  
  303.    if (T->Valued) Temp.Value.P = (XtPointer) T->Parent;
  304.    else           Temp.Value.P = (XtPointer) T->ValueOwner->Parent;
  305.    Temp.Type = MWidget;
  306.    Temp.Dynamic = FALSE;
  307.  
  308.    return Temp;   
  309. }
  310. MidasOperand MidasGetIngotOption(w,Name)
  311. Widget w;
  312. char *Name;
  313. {
  314.    MidasOperand Temp;
  315.    Ingot *T = MidasFindIngot(w,Name);
  316.    if (T == 0) MidasError("Can not find ingot %s",Name);
  317.  
  318.    Temp.Value.I = T->ExecuteWhenCreated;
  319.    Temp.Type = MBoolean;
  320.    Temp.Dynamic = FALSE;
  321.  
  322.    return Temp;   
  323. }
  324. void MidasSetIngotOption(w,Name,Opt)
  325. Widget w;
  326. char *Name;
  327. Boolean Opt;
  328. {
  329.    MidasOperand Temp;
  330.    Ingot *T = MidasFindIngot(w,Name);
  331.    if (T == 0) MidasError("Can not find ingot %s",Name);
  332.  
  333.    T->ExecuteWhenCreated = Opt;  
  334. }
  335. void MidasSetIngot(w,Name,Temp)
  336. Widget w;
  337. char *Name;
  338. MidasOperand Temp;
  339. {
  340.    Ingot *T = MidasCreateIngot(w, Name);
  341.    MidasSetIngotValue(T, Temp);
  342. #ifdef debug
  343.    printf("Set Ingot %s in %s to value %s\n",Name,XtName(w),Temp.Value.I);
  344. #endif
  345. }
  346. void MidasSetIngotString(w,Name,Value)
  347. Widget w; 
  348. char *Name;
  349. char *Value;
  350. {
  351.    MidasSetIngot(w,Name,MidasConvertFromString(Value));
  352. }
  353. void MidasSetIngotP(w,Name,Temp)
  354. Widget w;
  355. char *Name;
  356. MidasOperand *Temp;
  357. {
  358.    MidasSetIngot(w,Name,*Temp);
  359. }
  360. void MidasSetCallback(w,Name,Command)
  361. Widget w;
  362. char *Name;
  363. char *Command;
  364. {
  365.    Ingot *T = MidasCreateIngot(w, Name);
  366.    MidasInheritIngotValue(T,Name);
  367.    MidasSetCallbackValue(T,Command);
  368. }
  369. void MidasGetIngots(L,w)
  370. List *L;
  371. Widget w;
  372. {
  373.     MidasShell *ms = MidasGetShell(w);
  374.  
  375.     MidasEmptyList(L);
  376.  
  377.     for (;; w = XtParent(w))
  378.       {
  379.         MidasWidget *mw = MidasWidgetToMW(w);
  380.         ListItem *i;
  381.         List *TList = mw->IngotList; 
  382.    
  383.         if (TList != NULL)
  384.           for (i = TList->First; i != 0; i = i->Next)
  385.             if (strncmp(i->Entry,"midas",5))
  386.               if (MidasFindItemInList(L,i->Entry) == 0)
  387.                 MidasAddItemToList(L,i->Entry);
  388.  
  389.         if (w == ms->Widget) break; 
  390.       }
  391. }
  392. static void MidasStoreCallback(w,cname)
  393. Widget w;
  394. char *cname;
  395. {
  396.     char *result;
  397.     char *name = MidasGetWidgetName(w);
  398.     char *value = MidasConvertToString(MidasGetCallback(w,cname));
  399.     char *new = XtMalloc(strlen(name)+strlen(cname)+strlen(Option)+2);
  400.     MidasShell *ms = MidasGetShell(w);
  401.  
  402.     XtGetApplicationResources(w,(XtPointer) &result,resources,1,NULL,0);
  403.     strcpy(new,name);
  404.     strcat(new,".");
  405.     strcat(new,cname);
  406.     XrmPutStringResource(&ms->Database,new,value);
  407.  
  408.     strcat(new,Option);
  409.     value = MidasConvertToString(MidasGetIngotOption(w,cname));
  410.     XrmPutStringResource(&ms->Database,new,value);
  411.  
  412.     ms->Changes++;
  413.  
  414.     XtFree(new);
  415.     XtFree(value);
  416.  
  417.     if (result != 0)
  418.       {
  419.         Boolean found = FALSE;
  420.         char *token, *old = XtNewString(result);
  421.  
  422.         for (token = strtok(old," "); token != NULL; token = strtok(NULL," "))
  423.           if (strcmp(token,cname)==0) found = TRUE;
  424.  
  425.         XtFree(old);
  426.         if (found) { XtFree(name); return; }
  427.         value = XtMalloc(strlen(result)+strlen(cname)+2);
  428.         strcpy(value,result);
  429.         strcat(value," ");
  430.         strcat(value,cname);
  431.       }
  432.     else value = XtNewString(cname);
  433.       
  434.     new = XtMalloc(strlen(name)+strlen(".midasIngots")+1);
  435.     strcpy(new,name);
  436.     strcat(new,".midasIngots");
  437.   
  438.     XrmPutStringResource(&ms->Database,new,value);
  439.  
  440.     XtFree(new);
  441.     XtFree(value);
  442.     XtFree(name);
  443. }
  444. void MidasSetupIngots(mw,IngotNames)
  445. MidasWidget *mw;
  446. char *IngotNames;
  447. {
  448.     List *TList;
  449.     ListItem *item;
  450.     char *Input = XtNewString(IngotNames);
  451.     char *VerbVector[100];
  452.     int VerbCount, i;
  453.     Widget w = mw->Widget;
  454.     MidasShell *ms = MidasGetShell(w);
  455.  
  456.     mw->IngotList = TList = MidasCreateEmptyList(XtName(w));
  457.  
  458.     MidasTokenizeCommand(Input,VerbVector,&VerbCount,XtNumber(VerbVector)," ");
  459. /*
  460.     This could be made more efficient by fetching all the ingots at once
  461. */
  462.     for (i = 0; i < VerbCount; i++)
  463.       {
  464.         IngotParm result;
  465.         Ingot *T = XtNew(Ingot);
  466.         XtResource *temp;
  467.         ListItem *item = MidasFindItemInList(IngotRList,VerbVector[i]);
  468.         if (item == 0)
  469.           {
  470.             temp = (XtResource *) XtMalloc(sizeof(XtResource)*2);
  471.             temp[0] = resources[0];
  472.             temp[1] = resources[1]; 
  473.             temp[0].resource_name = XtNewString(VerbVector[i]);
  474.             temp[1].resource_name = strcpy(XtMalloc(strlen(VerbVector[i])+strlen(Option)+1),VerbVector[i]);
  475.             strcat(temp[1].resource_name,Option);
  476.  
  477.             item = MidasAddItemToList(IngotRList,temp->resource_name);
  478.             item->Pointer = temp;
  479.           }
  480.         else temp = item->Pointer;
  481.      
  482.         XtGetApplicationResources(w,(XtPointer) &result,temp,XtNumber(resources),
  483.                                   NULL,0);
  484.  
  485.         if (result.Command == 0 || *result.Command == '\0') T->Command = 0;
  486.         else T->Command = XtNewString(result.Command);
  487.         T->Valued = 0;
  488.         T->Parent = w;
  489.         T->ValueOwner = 0;
  490.         T->CallbackList = 0;
  491.         T->ExecuteWhenCreated = result.ExecuteWhenCreated;
  492.  
  493.         item = MidasAddItemToList(TList,VerbVector[i]);
  494.         item->Pointer = T;
  495.       }
  496.     XtFree(Input);
  497.  
  498.     for (item = TList->First; item != 0; item = item->Next)
  499.       {
  500.         Widget SW;
  501.         Ingot *T = item->Pointer;
  502.  
  503.         if (T->Valued == 0) MidasInheritIngotValue(T,item->Entry);
  504.         if (T->Command != 0) 
  505.           {
  506.             if (T->Valued == 0)
  507.               {
  508.                 ListItem *item;
  509.                 Ingot *ValueOwner = T->ValueOwner;
  510.                 if (ValueOwner->CallbackList == 0) ValueOwner->CallbackList = MidasCreateEmptyList("");
  511.                 item = MidasAddItemToListPos(ValueOwner->CallbackList,XtName(w),0);
  512.                 item->Pointer = T;
  513.               } 
  514.             if (T->ExecuteWhenCreated) MidasQueueCommand(w,T->Command);
  515.           }
  516.       }
  517. }
  518. void MidasInitializeIngots()
  519. {
  520.     IngotRList = MidasCreateEmptyList("IngotResourceList");
  521.     MidasDeclareFunction("GETINGOT(Widget,name)"           ,MidasGetIngot);
  522.     MidasDeclareFunction("GETCALLBACK(Widget,name)"        ,MidasGetCallback);
  523.     MidasDeclareFunction("GETVALUEOWNER(Widget,name)"      ,MidasGetValueOwner);
  524.     MidasDeclareFunction("GETINGOTOPTION(Widget,name)"     ,MidasGetIngotOption);
  525.     MidasDeclareVerb("SET INGOT Widget *name any..."       ,MidasSetIngotP);   
  526.     MidasDeclareVerb("GET INGOTS list Widget"              ,MidasGetIngots);
  527.     MidasDeclareVerb("SET CALLBACK Widget name name...",    MidasSetCallback);
  528.     MidasDeclareVerb("SET INGOT OPTION Widget name Boolean",MidasSetIngotOption);
  529.     MidasDeclareVerb("STORE CALLBACK Widget name",          MidasStoreCallback);
  530. }
  531.